// 插件管理器
package pluginmng

import (
	"context"
	"fmt"
	"os"
	"path/filepath"
	"sync"
	"syscall"
	"unsafe"

	x "gitee.com/shexk/uninm/interfaces"
)

// 插件信息
type pluginInfo struct {
	plugin   x.Plugin
	metadata x.Metadata
	path     string
	loaded   bool
	handle   unsafe.Pointer // DLL句柄
}

// 插件管理器
type Manager struct {
	plugins   map[string]*pluginInfo
	host      x.HostInterface
	pluginDir string
	mutex     sync.RWMutex
	ctx       context.Context
	cancel    context.CancelFunc
	config    map[string]interface{}
}

// 创建新的插件管理器
func NewManager(pluginDir string, host x.HostInterface, config map[string]interface{}) *Manager {
	ctx, cancel := context.WithCancel(context.Background())
	return &Manager{
		plugins:   make(map[string]*pluginInfo),
		host:      host,
		pluginDir: pluginDir,
		ctx:       ctx,
		cancel:    cancel,
		config:    config,
	}
}

// 加载单个插件
func (m *Manager) LoadPlugin(path string) error {
	m.mutex.Lock()
	defer m.mutex.Unlock()

	// 检查文件是否存在
	if _, err := os.Stat(path); os.IsNotExist(err) {
		return fmt.Errorf("plugin file not found: %s", path)
	}

	// 在Windows上使用syscall加载DLL
	handle, err := syscall.LoadLibrary(path)
	if err != nil {
		return fmt.Errorf("failed to load plugin: %v", err)
	}

	// 获取插件注册函数
	proc, err := syscall.GetProcAddress(handle, "RegisterPlugin")
	if err != nil {
		syscall.FreeLibrary(handle)
		return fmt.Errorf("failed to find RegisterPlugin function: %v", err)
	}

	// 转换为函数指针并调用
	registerFunc := (*func() (x.Plugin, error))(unsafe.Pointer(&proc))
	pluginInstance, err := (*registerFunc)()
	if err != nil {
		syscall.FreeLibrary(handle)
		return fmt.Errorf("failed to create plugin instance: %v", err)
	}

	// 获取元数据
	metadata := pluginInstance.Metadata()

	// 检查是否已加载
	if _, exists := m.plugins[metadata.ID]; exists {
		syscall.FreeLibrary(handle)
		return x.ErrPluginAlreadyLoaded
	}

	// 设置宿主接口
	pluginInstance.SetHost(m.host)

	// 初始化插件
	pluginConfig := make(map[string]interface{})
	if configs, ok := m.config["plugins"].(map[string]interface{}); ok {
		if pc, ok := configs[metadata.ID].(map[string]interface{}); ok {
			pluginConfig = pc
		}
	}

	if err := pluginInstance.Init(pluginConfig); err != nil {
		syscall.FreeLibrary(handle)
		return fmt.Errorf("plugin initialization failed: %v", err)
	}

	// 启动插件
	if err := pluginInstance.Start(m.ctx); err != nil {
		syscall.FreeLibrary(handle)
		return fmt.Errorf("plugin start failed: %v", err)
	}

	// 保存插件信息
	m.plugins[metadata.ID] = &pluginInfo{
		plugin:   pluginInstance,
		metadata: metadata,
		path:     path,
		loaded:   true,
		handle:   unsafe.Pointer(handle),
	}

	return nil
}

// 从目录加载所有插件
func (m *Manager) LoadPluginsFromDir() error {
	if _, err := os.Stat(m.pluginDir); os.IsNotExist(err) {
		return fmt.Errorf("plugin directory not found: %s", m.pluginDir)
	}

	// 查找目录中所有.dll文件
	dllFiles, err := filepath.Glob(filepath.Join(m.pluginDir, "*.dll"))
	if err != nil {
		return fmt.Errorf("failed to find plugin files: %v", err)
	}

	// 加载每个插件
	for _, file := range dllFiles {
		if err := m.LoadPlugin(file); err != nil {
			fmt.Printf("Warning: failed to load plugin %s: %v\n", file, err)
		}
	}

	return nil
}

// 卸载插件
func (m *Manager) UnloadPlugin(pluginID string) error {
	m.mutex.Lock()
	defer m.mutex.Unlock()

	pluginInfo, exists := m.plugins[pluginID]
	if !exists {
		return x.ErrPluginNotFound
	}

	// 停止插件
	if err := pluginInfo.plugin.Stop(); err != nil {
		fmt.Printf("Warning: error stopping plugin %s: %v\n", pluginID, err)
	}

	// 释放DLL
	handle := syscall.Handle(pluginInfo.handle)
	if err := syscall.FreeLibrary(handle); err != nil {
		return fmt.Errorf("failed to free plugin library: %v", err)
	}

	// 从插件列表移除
	delete(m.plugins, pluginID)
	return nil
}

// 获取所有插件元数据
func (m *Manager) GetAllPlugins() []x.Metadata {
	m.mutex.RLock()
	defer m.mutex.RUnlock()

	metadataList := make([]x.Metadata, 0, len(m.plugins))
	for _, info := range m.plugins {
		metadataList = append(metadataList, info.metadata)
	}
	return metadataList
}

// 调用插件
func (m *Manager) CallPlugin(pluginID string, req x.Request) (x.Response, error) {
	m.mutex.RLock()
	defer m.mutex.RUnlock()

	pluginInfo, exists := m.plugins[pluginID]
	if !exists {
		return x.Response{Success: false, Error: x.ErrPluginNotFound.Error()}, x.ErrPluginNotFound
	}

	return pluginInfo.plugin.HandleRequest(req)
}

// 关闭管理器，卸载所有插件
func (m *Manager) Close() {
	m.cancel() // 取消上下文，通知所有插件退出

	m.mutex.Lock()
	defer m.mutex.Unlock()

	// 卸载所有插件
	for id, info := range m.plugins {
		if err := info.plugin.Stop(); err != nil {
			fmt.Printf("Warning: error stopping plugin %s: %v\n", id, err)
		}

		handle := syscall.Handle(info.handle)
		if err := syscall.FreeLibrary(handle); err != nil {
			fmt.Printf("Warning: error unloading plugin %s: %v\n", id, err)
		}
	}

	m.plugins = make(map[string]*pluginInfo)
}
